﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TileEngine.items;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using TileEngine.recipes;

namespace TileEngine.inventory
{
    class Inventory
    {
        public List<Holder> holders;
        public Holder[] accessoryHolders;
        public Holder mouseHolder;
        public Holder armorHolder;
        public Holder vanityHolder;
        public Holder trashHolder;
        public Player player;
        public List<List<Holder>> craftingHolders;


        public bool isShown=true;
        public int selected=0;
        public int holderSize = 30;
        int inventoryWidth = 8;
        int inventoryHeight = 12;

        int mouseScroll=0;
        bool mouseLeft = false;
        bool mouseRight = false;

        public int craftScrollIndex = 0;
        public List<Recipe> availableRecipes;
        public Holder craftHolder;

        public Inventory(Player player)
        {
            this.player = player;
            holders = new List<Holder>();
            for (int i = 0; i < inventoryWidth; i++)
            {
                for (int j = 0; j < inventoryHeight; j++)
                {
                    holders.Add(new Holder(new Rectangle((int)Camera.screenDimension.X-40-holderSize-i*holderSize,
                                                         40*2+holderSize+j*holderSize,holderSize,holderSize)));
                    if (i == 0)
                    {
                        holders.Last().setHotkey(Keys.K);
                    }
                }
            }

            accessoryHolders = new Holder[inventoryWidth];
            for (int i = 0; i < inventoryWidth; i++)
            {
                accessoryHolders[i] = new Holder(new Rectangle((int)Camera.screenDimension.X - 40 - (i+1) * holderSize, 40, holderSize, holderSize));
            }
            mouseHolder = new Holder();
            armorHolder = new Holder(new Rectangle((int)Camera.screenDimension.X-40-inventoryWidth*holderSize+50,
                                                        80+(inventoryHeight+1)*holderSize+40,holderSize,holderSize));
            vanityHolder = new Holder(new Rectangle((int)Camera.screenDimension.X - 40 - inventoryWidth * holderSize + 50,
                                                        80 + (inventoryHeight + 2) * holderSize + 40, holderSize, holderSize));
            craftHolder = new Holder(new Rectangle((int)Camera.screenDimension.X - 40 - holderSize - inventoryWidth * holderSize,
                                                        40 * 2 + (inventoryHeight-1) * (holderSize), holderSize, holderSize));
            trashHolder = new Holder(new Rectangle((int)Camera.screenDimension.X - 40 - holderSize - inventoryWidth * holderSize,
                                                        40 * 2 + inventoryHeight * holderSize, holderSize, holderSize));

            mouseScroll = Mouse.GetState().ScrollWheelValue;
            availableRecipes = new List<Recipe>();
            craftingHolders = new List<List<Holder>>();
            for (int i = 0; i < inventoryHeight; i++)
            {
                craftingHolders.Add(new List<Holder>());
            }
        }
        public void update(GameTime gameTime, KeyboardState keys)
        {
            if (isShown)
            {
                if (Mouse.GetState().LeftButton == ButtonState.Released)
                    mouseLeft = false;
                if (Mouse.GetState().RightButton == ButtonState.Released)
                    mouseRight = false;
                if (Mouse.GetState().RightButton == ButtonState.Pressed && !mouseRight)
                {
                    mouseRight = true;
                    Holder get = getClickedHolder();
                    if (get != null && !get.islocked && get.items.Count != 0)
                    {
                            if (mouseHolder.addItem(get.items.Last()))
                            {
                                get.items.RemoveAt(get.items.Count - 1);
                            }
                    }
                    else if (get != null)
                    {
                        for (int i = 0; i < inventoryHeight; i++)
                        {
                            if(craftingHolders[i].Count!=0)
                            {
                                if(get.Equals(craftingHolders[i][0])){
                                    craft(craftingHolders[i][0].items[0].GetType());
                                    break;
                                }
                            }
                        }
                    }
                }
                if (Mouse.GetState().LeftButton == ButtonState.Pressed && !mouseLeft)
                {
                    mouseLeft = true;
                    Holder get = getClickedHolder();
                    if (get == null)
                        return;

                    if (mouseHolder.items.Count == 0)
                    {
                        movetoMouseHolder(get);
                    }
                    else
                    {
                        if (get.items.Count != 0)
                        {
                            if (mouseHolder.items[0].GetType() != get.items[0].GetType())
                                switchHolders(get, mouseHolder);
                            else
                                moveFromMouseHolder(get);
                        }
                        else
                            moveFromMouseHolder(get);
                    }
                }
            }
            else
            {
                if (Mouse.GetState().RightButton == ButtonState.Pressed && !mouseRight)
                {
                    mouseRight = true;
                }
                if (Mouse.GetState().LeftButton == ButtonState.Pressed && !mouseLeft)
                {

                    mouseLeft = true;
                }

            }
            if (mouseScroll > Mouse.GetState().ScrollWheelValue)
            {
                if (isShown)
                {
                    if (craftScrollIndex != availableRecipes.Count)
                        craftScrollIndex++;
                    craftHoldersChanged();
                }
                else
                    selected = (selected + 1) % inventoryHeight;
            }
            if (mouseScroll < Mouse.GetState().ScrollWheelValue)
            {
                if (isShown)
                {
                    if (craftScrollIndex != 0)
                        craftScrollIndex--;
                    craftHoldersChanged();
                }
                else
                    selected = (selected - 1 + inventoryHeight) % inventoryHeight;
            }
            mouseScroll = Mouse.GetState().ScrollWheelValue;
        }
        public void draw(SpriteBatch spriteBatch)
        {
            //spriteBatch.Draw(Textures.back, new Rectangle(0, 0, (int)Camera.screenDimension.X,(int) Camera.screenDimension.Y), new Color(255, 255, 255, 100));
            if (isShown)
            {
                drawAccessories(spriteBatch);
                drawInventory(spriteBatch);
                armorHolder.draw(spriteBatch, false);
                vanityHolder.draw(spriteBatch, false);
                trashHolder.draw(spriteBatch, true);
                craftHolder.draw(spriteBatch, true);
                drawCrafting(spriteBatch);
                if (mouseHolder.items.Count != 0)
                    mouseHolder.draw(spriteBatch, new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, holderSize, holderSize));

                spriteBatch.DrawString(Textures.font10Bold, "Trash:", new Vector2(trashHolder.bounds.Left - 50, trashHolder.bounds.Top), Color.White);
                spriteBatch.DrawString(Textures.font10Bold, "Recipes With:", new Vector2(trashHolder.bounds.Left - 106, craftHolder.bounds.Top), Color.White);
                spriteBatch.DrawString(Textures.font10Bold, "Accessories:", new Vector2(trashHolder.bounds.Left - 100 + holderSize, 40), Color.White);

                spriteBatch.DrawString(Textures.font10Bold, "Armor:", new Vector2(armorHolder.bounds.Left - 50, armorHolder.bounds.Top), Color.White);
                spriteBatch.DrawString(Textures.font10Bold, "Vanity:", new Vector2(vanityHolder.bounds.Left - 58, vanityHolder.bounds.Top), Color.White);
                Holder onMove = getClickedHolder();
                if (onMove != null && onMove.items.Count != 0)
                {
                    int xPos;
                    if (Mouse.GetState().X > Camera.screenDimension.X - 200)
                        xPos = (int)Camera.screenDimension.X - 200;
                    else
                        xPos = Mouse.GetState().X + 20;
                    string[] lines = onMove.items[0].getInfo();
                    for (int i = 0; i < lines.Length; i++)
                    {
                        spriteBatch.DrawString(Textures.font10Bold, lines[i], new Vector2(xPos, Mouse.GetState().Y + i * 10 + 10), Color.White);
                    }
                }

                drawStats(spriteBatch);
            }
            drawHotbar(spriteBatch);

        }

        public bool addItem(Iitem item){
            for (int i = 0; i < holders.Count; i++)
			{
                if (holders[i].addItem(item))
                    return true;
			}
            return false;
        }
        Holder getClickedHolder()
        {
            Point mouse = new Point(Mouse.GetState().X, Mouse.GetState().Y);
            if (isShown)
            {
                for (int i = 0; i < holders.Count; i++)
                {
                    if (holders[i].bounds.Contains(mouse))
                    {
                        return holders[i];
                    }
                }
                for (int i = 0; i < accessoryHolders.Length; i++)
                {
                    if (accessoryHolders[i].bounds.Contains(mouse))
                        return accessoryHolders[i];
                }
                if (trashHolder.bounds.Contains(mouse))
                    return trashHolder;
                if (armorHolder.bounds.Contains(mouse))
                    return armorHolder;
                if (vanityHolder.bounds.Contains(mouse))
                    return vanityHolder;
                if (craftHolder.bounds.Contains(mouse))
                    return craftHolder;
                for (int i = 0; i < inventoryHeight; i++)
                {
                    for (int j = 0; j < craftingHolders[i].Count; j++)
                    {
                        if (craftingHolders[i][j].bounds.Contains(mouse))
                        {
                            return craftingHolders[i][j];
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < inventoryHeight; i++)
                {
                    if (holders[i].bounds.Contains(mouse))
                    {
                        return holders[i];
                    }
                }
            }
            return null;
        }
        void switchHolders(Holder a, Holder b)
        {
            if (a.islocked)
                return;
            if (b.islocked)
                return;
            List<Iitem> hold = new List<Iitem>();
            for (int i = 0; i < a.items.Count; i++)
            {
                hold.Add(a.items[i]);
            }
            a.items.Clear();
            for (int i = 0; i < b.items.Count; i++)
            {
                a.items.Add(b.items[i]);
            }
            b.items.Clear();
            for (int i = 0; i < hold.Count; i++)
            {
                b.items.Add(hold[i]);
            }
        }
        void movetoMouseHolder(Holder a)
        {
            if (a.islocked)
                return;
            for (int i = a.items.Count - 1; i > -1; i--)
            {
                if (mouseHolder.addItem(a.items[i]))
                {
                    a.items.RemoveAt(i);
                }
            }
        }
        void moveFromMouseHolder(Holder a)
        {
            if (!a.canAdd)
                return;
            for (int i = mouseHolder.items.Count - 1; i > -1; i--)
            {
                if (a.addItem(mouseHolder.items[i]))
                {
                    mouseHolder.items.RemoveAt(i);
                }
            }
        }
        
        void drawHotbar(SpriteBatch spriteBatch)
        {
            for (int i = 0; i < inventoryHeight; i++)
                if(i==selected)
                    holders[i].draw(spriteBatch,false);
                else
                    holders[i].draw(spriteBatch,true);
        }
        void drawAccessories(SpriteBatch spriteBatch)
        {
            for (int i = 0; i < inventoryWidth; i++)
            {
                accessoryHolders[i].draw(spriteBatch,false);
            }
        }
        void drawInventory(SpriteBatch spriteBatch)
        {
            for (int i = inventoryHeight; i < holders.Count; i++)
            {
                holders[i].draw(spriteBatch,false);
            }

        }
        void drawStats(SpriteBatch spriteBatch)
        {
            int y = 40 + (inventoryHeight+1) * holderSize + 40+40;
            int x = (int)Camera.screenDimension.X - 40 - (inventoryWidth - 4) * holderSize;
            spriteBatch.Draw(Textures.addStat, new Vector2(x-15, y), new Rectangle(0, 0, 10, 10), Color.White);
            spriteBatch.Draw(Textures.addStat, new Vector2(x-15, y+16), new Rectangle(0, 0, 10, 10), Color.White);
            spriteBatch.Draw(Textures.addStat, new Vector2(x-15, y+16), new Rectangle(0, 0, 10, 10), Color.White);

            spriteBatch.DrawString(Textures.font10Bold, "Strenght:"+player.strenght, new Vector2(x, y), Color.White);
            spriteBatch.DrawString(Textures.font10Bold, "Intelligence:"+player.intelligence, new Vector2(x, y+16), Color.White);
            spriteBatch.DrawString(Textures.font10Bold, "Agility:" + player.agility, new Vector2(x, y + 32), Color.White);
        }
        #region crafting

        public bool doesInventoryHave(Type Item)
        {
            for (int i = 0; i < holders.Count; i++)
            {
                if (holders[i].items.Count != 0)
                    if (holders[i].items[0].GetType() == Item)
                        return true;
            }
            return false;
        }
        public bool doesInventoryHave(Type Item,int count)
        {
            for (int i = 0; i < holders.Count; i++)
            {
                if (holders[i].items.Count != 0)
                    if (holders[i].items[0].GetType() == Item)
                        count-=holders[i].items.Count;
                if (count <= 0)
                    return true;
            }
            return false;
        }  
        public bool getItems(Type Item, int count)
        {
            if (!doesInventoryHave(Item, count))
                return false;
            for (int i = 0; i < holders.Count; i++)
            {
                if (holders[i].items.Count != 0)
                    if (holders[i].items[0].GetType() == Item)
                    {
                        holders[i].items.RemoveAt(0);
                        count--;
                        i--;
                    }
                if (count == 0)
                    return true;
            }
            return true;
        }
        void drawCrafting(SpriteBatch spriteBatch)
        {
            for (int i = 0; i < craftingHolders.Count; i++)
            {
                for (int j = 0; j < craftingHolders[i].Count; j++)
                {
                    craftingHolders[i][j].drawRecipe(spriteBatch, Convert.ToBoolean(j) ? false : true);
                }
               
            }
        }
        public bool doesInventoryCraft(Recipe recipe)
        {
            if (craftHolder.items.Count != 0)
                if (!recipe.isContains(craftHolder.items[0].GetType()))
                    return false;
            if (recipe.tool != null)
                if (!doesInventoryHave(recipe.tool))
                    return false;
            for (int i = 0; i < recipe.ingredients.Count; i++)
            {
                if (!doesInventoryHave(recipe.ingredients[i].item, recipe.ingredients[i].count))
                    return false;
            }
            return true;
        }
        public void craft(Type item)
        {
            Recipe recipe = Recipes.getRecipe(item);
            if (doesInventoryCraft(recipe))
            {
                if (addItem(Activator.CreateInstance(item) as Iitem))
                {
                    for (int i = 0; i < recipe.ingredients.Count; i++)
                    {
                        getItems(recipe.ingredients[i].item, recipe.ingredients[i].count);
                    }
                    findAvailableRecipes();
                }
            }
        }
        public void findAvailableRecipes()
        {
            availableRecipes.Clear();
            for (int i = 0; i < Recipes.recipes.Count; i++)
            {
                if(craftHolder.items.Count!=0)
                    if(!Recipes.recipes[i].isContains(craftHolder.items[0].GetType()))
                        continue;
                if (doesInventoryCraft(Recipes.recipes[i]))
                {
                    availableRecipes.Add(Recipes.recipes[i]);
                }
            }
            craftHoldersChanged();
        }
        public void craftHoldersChanged()
        {
            int k = craftScrollIndex - inventoryHeight / 2;
            for (int i = 0; i < inventoryHeight; i++)
            {
                k++;
                craftingHolders[i].Clear();
                if (k >= 0 && k < availableRecipes.Count)
                {
                    craftingHolders[i].Add(new Holder(new Rectangle(40, 40 + i * holderSize, holderSize, holderSize), availableRecipes[k].output.count, availableRecipes[k].output.item));
                    craftingHolders[i].Last().canAdd = false;
                    craftingHolders[i].Last().islocked = true;
                    if (availableRecipes[k].tool != null)
                    {
                        craftingHolders[i].Add(new Holder(new Rectangle(40 + holderSize, 40 + i * holderSize, holderSize, holderSize), 0, availableRecipes[k].tool));
                        craftingHolders[i].Last().canAdd = false;
                        craftingHolders[i].Last().islocked = true;
                    }
                    for (int j = 0; j < availableRecipes[k].ingredients.Count; j++)
                    {
                        craftingHolders[i].Add(new Holder(new Rectangle(40 + holderSize * (2 + j), 40 + i * holderSize, holderSize, holderSize), availableRecipes[k].ingredients[j].count, availableRecipes[k].ingredients[j].item));
                        craftingHolders[i].Last().canAdd = false;
                        craftingHolders[i].Last().islocked = true;
                    }
                }
            }
        }
        #endregion
    }
}
